/*
 * Socket.h
 *
 *  Created on: Jul 30, 2013
 *      Author: m
 */

#ifndef SOCKET_H_
#define SOCKET_H_

#include <cstdlib>
#include <iostream>
#include <fstream>
#include "inet.h"
#include "Exception.h"

typedef int file_descriptor;
typedef int socket_port;

class Socket
{
protected:
    file_descriptor m_sockfd;

public:
    Socket() :
        m_sockfd( 0 )
    {
    }

    Socket( file_descriptor fd )
    {
        m_sockfd = fd;
    }

    virtual ~Socket()
    {
    }

    void listen( socket_port port )
    {
        m_sockfd = tcpoppas( port );

        if ( m_sockfd < 0)
        {
            throw Exception( "Socket: Error al hacer el listen." );
        }
    }

    void connect( std::string server, socket_port port )
    {
        m_sockfd = tcpopact( server.c_str(), port );

        if ( m_sockfd < 0 )
        {
            throw Exception( "Socket: Error al hacer el connect." );
        }
    }

    file_descriptor accept()
    {
        struct sockaddr_in  cli_addr;
        socklen_t clilen = sizeof(cli_addr);
        file_descriptor fdResult;

        fdResult = ::accept( m_sockfd, (struct sockaddr *) &cli_addr, &clilen);

        if ( fdResult < 0 )
        {
            throw Exception( "Socket: Error al hacer el accept." );
        }

        return fdResult;
    }

    void send( void *data, size_t nbytes )
    {
        int nbytesSent;

        nbytesSent = enviar( m_sockfd, (void *) data, nbytes );

        if ( nbytesSent != nbytes )
        {
            throw Exception( "Socket: Error al enviar los datos." );
        }
    }

    void recv( void *data, size_t nbytes )
    {
        int nbytesRecieved;

        nbytesRecieved = recibir( m_sockfd, (void *)data, nbytes);

        if ( nbytesRecieved != nbytes )
        {
            throw Exception( "Socket: Error al recibir los datos." );
        }
    }

    void close()
    {
        ::close( m_sockfd );
    }

};

#endif /* SOCKET_H_ */
